﻿// Copyright (c) MichaConrad. All rights reserved. See License.txt in the project root for license information.

namespace LinqToLdapExtensions.Tests.Integration
{
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using LinqToLdap;
    using LinqToLdapExtensions.Domain;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
        Justification = "Reviewed. Suppression is OK here.")]
    [TestClass]
    public class IntegrationTests
    {
        private static DirectoryContextUnitOfWork unitOfWorkThreadStatic;
        private static DirectoryContextUnitOfWork unitOfWorkWeb;

        [ClassInitialize]
        public static void TestInit(TestContext ctx)
        {
            unitOfWorkThreadStatic = IntegrationTestHelper.SetupUnitOfWork(ScopeState.ThreadStatic);
            unitOfWorkWeb = IntegrationTestHelper.SetupUnitOfWork(ScopeState.WebContext);
        }

        [ClassCleanup]
        public static void ClassCleanup()
        {
        }

        [TestInitialize]
        public void Init()
        {
        }

        [TestMethod]
        [TestCategory("Integration")]
        public void IntegrationSimpleQuery()
        {
            unitOfWorkThreadStatic.BeginUnitOfWork();

            RunTestQuery(unitOfWorkThreadStatic);

            unitOfWorkThreadStatic.EndUnitOfWork();
        }
        
        [TestMethod]
        [TestCategory("Integration")]
        public void IntegrationMultithreadedQueryThreadStatic()
        {
            unitOfWorkThreadStatic.BeginUnitOfWork();
            Assert.IsNotNull(unitOfWorkThreadStatic.CurrentContext);

            var errors = TestHelper.RunThreadedTest(
                threads: 20,
                iterations: 5,
                test: () =>
                {
                    unitOfWorkThreadStatic.BeginUnitOfWork();

                    RunTestQuery(unitOfWorkThreadStatic);

                    unitOfWorkThreadStatic.EndUnitOfWork();
                });

            if (errors.Count() > 0)
            {
                throw errors[0];
            }

            unitOfWorkThreadStatic.EndUnitOfWork();
        }

        [TestMethod]
        [TestCategory("Integration")]
        public void IntegrationMultithreadedQueryWeb()
        {
            TestHelper.MockHttpContext();

            unitOfWorkWeb.BeginUnitOfWork();
            Assert.IsNotNull(unitOfWorkWeb.CurrentContext);

            var errors = TestHelper.RunThreadedTest(
                threads: 20,
                iterations: 5,
                test: () =>
                {
                    TestHelper.MockHttpContext();

                    unitOfWorkWeb.BeginUnitOfWork();

                    RunTestQuery(unitOfWorkWeb);

                    unitOfWorkWeb.EndUnitOfWork();
                });

            if (errors.Count() > 0)
            {
                throw errors[0];
            }

            unitOfWorkWeb.EndUnitOfWork();
        }
        
        private static void RunTestQuery(DirectoryContextUnitOfWork unitOfWork)
        {
            var baseDn = unitOfWork.CurrentContext.ListServerAttributes("namingcontexts").GetStrings("namingcontexts").First();
            Assert.IsTrue(!string.IsNullOrWhiteSpace(baseDn));

            var result = unitOfWork.CurrentContext.Query<InetOrgPerson>(
                    System.DirectoryServices.Protocols.SearchScope.OneLevel)
                           .Take(100).ToList();

            Assert.IsTrue(result.Count() == 100);
        }
    }
}
